package com.vogue.supplymall.order.domain.biz.impl;

import com.vogue.supplymall.common.constant.ConstantBean;
import com.vogue.supplymall.common.domain.dto.OrderDetailInfo;
import com.vogue.supplymall.common.domain.dto.SearchPrepayInfo;
import com.vogue.supplymall.common.domain.dto.UploadInfo;
import com.vogue.supplymall.common.domain.dto.UploadToDBInfo;
import com.vogue.supplymall.common.domain.dto.UserInfo;
import com.vogue.supplymall.common.exception.DataNotFindException;
import com.vogue.supplymall.order.domain.biz.OrderDetailBiz;
import com.vogue.supplymall.order.domain.biz.OrderUpdateBiz;
import com.vogue.supplymall.order.domain.biz.PrepaySearchBiz;
import com.vogue.supplymall.order.domain.model.Fulfillment;
import com.vogue.supplymall.order.domain.model.OrderCancel;
import com.vogue.supplymall.order.domain.model.OrderPayVoucher;
import com.vogue.supplymall.order.domain.model.OrderPayment;
import com.vogue.supplymall.order.domain.model.OrderStatus;
import com.vogue.supplymall.order.domain.service.FulfillmentService;
import com.vogue.supplymall.order.domain.service.OrderCancelService;
import com.vogue.supplymall.order.domain.service.OrderItemProductService;
import com.vogue.supplymall.order.domain.service.OrderPayVoucherService;
import com.vogue.supplymall.order.domain.service.OrderPaymentService;
import com.vogue.supplymall.order.domain.service.OrderService;
import com.vogue.supplymall.order.domain.service.OrderStatusService;
import com.vogue.supplymall.order.exception.AddExpressException;
import com.vogue.supplymall.order.exception.UpdateOrderException;
import com.vogue.supplymall.shop.domain.model.ProductAttrplan;
import com.vogue.supplymall.shop.domain.service.ProductAttrplanService;
import com.vogue.supplymall.upload.domain.service.UploadService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * The type Order detail biz.
 *
 * @aouthor: zhangliang
 * @date: Create in 2018-02-06
 */
@Service("orderDetailBiz")
public class OrderDetailBizImpl implements OrderDetailBiz {
    /**
     * The constant LOGGER_ORDERDETAILBIZIMPL.
     */
    public static final Logger LOGGER_ORDERDETAILBIZIMPL = LoggerFactory.getLogger(OrderDetailBizImpl.class);

    @Resource
    private OrderService orderService;
    @Resource
    private ProductAttrplanService productAttrplanService;
    @Resource
    private OrderItemProductService orderItemProductService;
    @Resource
    private OrderStatusService orderStatusService;
    @Resource
    private OrderCancelService orderCancelService;
    @Resource
    private FulfillmentService fulfillmentService;
    @Resource
    private OrderPayVoucherService orderPayVoucherService;
    @Resource
    private UploadService uploadService;
    @Resource
    private OrderPaymentService orderPaymentService;
    @Resource
    private OrderUpdateBiz orderUpdateBiz;
    @Resource
    private PrepaySearchBiz prepaySearchBiz;
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /*获取订单买家*/
    private Function<Map<String, Object>, Map<String, Object>> getOrderBuyer = (firstData) -> firstData
            .entrySet()
            .stream()
            .filter((entry) -> entry.getKey().startsWith("ob"))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    /*获取订单卖家*/
    private Function<Map<String, Object>, Map<String, Object>> getOrderSeller = (firstData) -> firstData
            .entrySet()
            .stream()
            .filter((entry) -> entry.getKey().startsWith("os"))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    /*goodsData内容过滤*/
    private Function<List<Map<String, Object>>, List<Map<String, Object>>> fiterGoodsData = (list) -> list
            .stream()
            .map((Map<String, Object> map) -> map.entrySet()
                    .parallelStream()
                    .filter((entry) -> !entry.getKey().startsWith("os") ||
                            !entry.getKey().startsWith("ob") ||
                            !entry.getKey().startsWith("oc") ||
                            !entry.getKey().startsWith("op"))
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))
            .collect(Collectors.toList());
    /*2018/4/3 统计订单商品重量*/
    private Function<List<Map<String, Object>>, BigDecimal> calcTotalWeight = (list) -> list
            .stream()
            .map((Map<String, Object> map) -> new BigDecimal(map.get("weight").toString()).multiply(new BigDecimal(map.get("itemquantity").toString())))
            .reduce(BigDecimal.ZERO, (acc, x) -> acc.add(x));
    /*2018/4/3 统计订单计件数量*/
    private Function<List<Map<String, Object>>, Integer> calcTotalItemCount = (list) -> list
            .stream()
            .map((Map<String, Object> map) -> map.get("weight").toString().equals("0") ? new Integer(map.get("itemquantity").toString()) : 0)
            .reduce(0, (acc, x) -> acc + x);
    /*2018/4/9 订单支付信息*/
    private Function<Map<String, Object>, Map<String, Object>> getPaymentInfo = (firstData) -> firstData
            .entrySet()
            .stream()
            .filter((entry) -> entry.getKey().startsWith("op_"))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    /*物流信息内容过滤*/
    private Function<Map<String, Object>, Map<String, Object>> fulfillment = (firstData) -> firstData
            .entrySet()
            .stream()
            .filter((entry) -> entry.getKey().startsWith("ffm"))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    @Override
    public Map<String, Object> findOrderDetail(OrderDetailInfo detailInfo, UserInfo userInfo) {
        List<Map<String, Object>> orderDetail = orderService.findOrderDetail(detailInfo);
        if (null == orderDetail) {
            throw new DataNotFindException("");
        }
        Map<String, Object> firstData = orderDetail.stream().findFirst().get();
        Map<String, Object> result = new HashMap<>();
        result.put("buyer", getOrderBuyer.apply(firstData));
        Map<String, Object> seller = getOrderSeller.apply(firstData);
        // 2018/10/29 查询预付款余额
        SearchPrepayInfo searchPrepayInfo = new SearchPrepayInfo();
        searchPrepayInfo.setSyscodeid(userInfo.getSyscodeid());
        searchPrepayInfo.setOrganid(userInfo.getOrganInfo().getId());
        searchPrepayInfo.setSellorganid(new Long(firstData.get("sellorganid").toString()));
        searchPrepayInfo.setSellsyscodeid(new Long(firstData.get("sellsyscodeid").toString()));
        Map<String, String> prepay = prepaySearchBiz.searchPrepayBalance(searchPrepayInfo);
        seller.put("paymode", prepay.get("paymode"));
        result.put("seller", seller);
        result.put("goodsData", fiterGoodsData.apply(orderDetail));
        // 2018/11/19 因为payment为多条，在后边另行查询
//        result.put("payment", getPaymentInfo.apply(firstData));
        //计算差异金额和实发金额
        BigDecimal sumDiffMoney = BigDecimal.ZERO;
        BigDecimal sumSendMoney = BigDecimal.ZERO;
        for (Map<String, Object> map : orderDetail) {
            sumDiffMoney = sumDiffMoney.add(new BigDecimal(map.get("diffmoney").toString()));
            sumSendMoney = sumSendMoney.add(new BigDecimal(map.get("sendmoney").toString()));
        }
        result.put("sumDiffMoney", sumDiffMoney);
        result.put("sumSendMoney", sumSendMoney);

        result.put("totalprice", firstData.get("totalprice"));
        result.put("totalquantity", firstData.get("totalquantity"));
        result.put("freight", firstData.get("freight"));
        result.put("orderstatus", firstData.get("orderstatus"));
        // 2018/2/26 add供应链侧是否拉取过订单
        result.put("pullstate", firstData.get("pullstate"));
        // 2018/7/2 添加买家拉取状态
        result.put("buypullstate", firstData.get("buypullstate"));
        result.put("memo", firstData.get("memo"));
        result.put("ordernumber", firstData.get("ordernumber"));
        result.put("finalprice", firstData.get("finalprice"));
        result.put("isInvoice", firstData.get("isInvoice"));
        List<OrderCancel> lists = orderCancelService.searchOrderCancel(detailInfo.getOrderid());
        if (lists.size() > 0) {
            result.put("oc_count", lists.size());
            result.put("oc_modifydate", lists.get(0).getModifyDate());
            result.put("cancelstate", lists.get(0).getCancelstate());
            result.put("cancelcause", lists.get(0).getCancelcause());
            result.put("othercause", lists.get(0).getOthercause());
        }
        result.put("createdate", firstData.get("createdate"));
        result.put("totleWeight", calcTotalWeight.apply(orderDetail));
        result.put("totleItemCount", calcTotalItemCount.apply(orderDetail));
        result.put("fulfillment", StringUtils.isNotEmpty((String) fulfillment.apply(firstData).get("ffm_number"))
                ? fulfillment.apply(firstData) : new HashMap<>());
        try {
            //如果是待支付状态需要判断是否已经支付成功如果是则需要刷新状态
            if (result.get("orderstatus").toString().equals("0")) {
                try {
                    result.put("orderstatus", orderUpdateBiz.refreshOrderPayStatus(detailInfo.getOrderid()).toString());
                } catch (Exception e) {
                    LOGGER_ORDERDETAILBIZIMPL.error("订单[{}]待付款状态刷新支付状态异常：{}"
                            , result.get("ordernumber")
                            , e.toString());
                }
            }
            //如果是待支付状态需要判断是否已经支付成功如果是则需要刷新状态
            long modifyTime = format.parse(firstData.get("modifydate").toString()).getTime();
            //订单修改时间和状态修改时间哪个更晚一些用哪个来计算过期值
            modifyTime = modifyTime < format.parse(firstData.get("ordermodifydate").toString()).getTime()
                    ? format.parse(firstData.get("ordermodifydate").toString()).getTime() : modifyTime;
            long currentTime = System.currentTimeMillis();
            /*付款超时设置*/
            long overTime = 0L;
            OrderStatus orderStatus = orderStatusService.get(detailInfo.getStatusid());
            if (!orderStatus.getIscancel()) {
                if (orderStatus.getOrderstatus() == 0) {
                    if ((currentTime - modifyTime) > ConstantBean.PAY_FAILURE_TIME && 0 == orderStatus.getOrderstatus()) {
                        orderStatus.setIscancel(true);
                        orderStatus.setModifyDate(new Date());
                        orderStatusService.update(orderStatus);
                        addOrderCancel(detailInfo, userInfo);
                        returnProductInventory(detailInfo);
                        orderUpdateBiz.orderPayCancel(orderStatus.getOrderid());
                    } else {
                        overTime = ConstantBean.PAY_FAILURE_TIME.longValue() - (currentTime - modifyTime);
                    }
                }
//                if (orderStatus.getOrderstatus() == 1) {
                /*待接单超时设置*/
//                    if ((currentTime - modifyTime) > ConstantBean.SELLER_AGREE_FAILURE_TIME && 1 == orderStatus.getOrderstatus()) {
//                        orderStatus.setIscancel(true);
//                        orderStatus.setModifyDate(new Date());
//                        orderStatusService.update(orderStatus);
//                        addOrderCancel(detailInfo, userInfo);
//                        returnProductInventory(detailInfo);
//                    }
//                }
            }
            /*待收货超时设置*/
            if (orderStatus.getOrderstatus() == 3) {
                if ((currentTime - modifyTime) > ConstantBean.CONFIRM_RECEIVE_TIME) {
                    orderStatus.setOrderstatus(4);
                    orderStatus.setModifyDate(new Date());
                    orderStatusService.update(orderStatus);
                    addOrderCancel(detailInfo, userInfo);
                    returnProductInventory(detailInfo);
                }
            }
            result.put("iscancel", orderStatus.getIscancel());
//            result.put("overTime", (currentTime - modifyTime - 3000L) / 1000);
            result.put("overTime", overTime / 1000);
            List<OrderPayment> paymentList = orderPaymentService.selectByWhr("orderid=" + detailInfo.getOrderid());
            result.put("paymentList", paymentList);
        } catch (ParseException e) {
            LOGGER_ORDERDETAILBIZIMPL.info("日期转换异常，付款倒计时被设置成0 ");
            result.put("payCountDown", 0);
        } catch (RuntimeException e) {
            throw new DataNotFindException("订单详情");
        }
        return result;
    }

    /**
     * 添加取消申请
     *
     * @param orderDetailInfo
     */
    private void addOrderCancel(OrderDetailInfo orderDetailInfo, UserInfo userInfo) {
        LOGGER_ORDERDETAILBIZIMPL.info(">>> 插入取消申请--超时直接取消 >>>");
        OrderCancel orderCancel = new OrderCancel();
        orderCancel.setOrderid(orderDetailInfo.getOrderid());
        orderCancel.setCancelcause(6);
        orderCancel.setCancelstate(0);
        orderCancel.setSyscodeid(userInfo.getSyscodeid());
        if (StringUtils.isEmpty(orderDetailInfo.getOthercauser())) {
            orderCancel.setOthercause("");
        } else {
            orderCancel.setOthercause(orderDetailInfo.getOthercauser());
        }
        orderCancelService.save(orderCancel);
    }

    /**
     * 更新商品计划
     *
     * @param orderDetailInfo
     */
    private void returnProductInventory(OrderDetailInfo orderDetailInfo) {
        LOGGER_ORDERDETAILBIZIMPL.info(">>> 详情 >>>更新商品计划 >>> 返还库存");
        try {
            List<Map<String, Object>> mapList = orderItemProductService.findOrderProduct(orderDetailInfo);
            mapList.forEach((Map<String, Object> map) -> {
                ProductAttrplan attrplan = productAttrplanService.get(new Long(map.get("attrplanid").toString()));
                BigDecimal inv = attrplan.getInventory().add(new BigDecimal(map.get("itemquantity").toString()));
                attrplan.setInventory(inv);
                attrplan.setModifyDate(new Date());
                productAttrplanService.update(attrplan);
            });
        } catch (RuntimeException e) {
            throw new DataNotFindException("");
        }
    }

    /**
     * Update fulfillment boolean.
     *
     * @param detailInfo the detail info
     * @return the boolean
     */
    @Override
    @Transactional
    public Long updateFulfillment(OrderDetailInfo detailInfo) {
        Map<String, String> express = detailInfo.getExpress();
        if (null == detailInfo.getExpress().get("id")) {
            LOGGER_ORDERDETAILBIZIMPL.info(">>> updateFulfillment 更新物流信息");
            if (fulfillmentService.getFulfillmentForRefund(new Long(detailInfo.getOrderid())) > 0) {
                LOGGER_ORDERDETAILBIZIMPL.info(">>> 物流信息已存在");
                throw new AddExpressException("");
            } else {
                try {
                    return insertFulfillment(detailInfo.getExpress(), detailInfo.getOrderid());
                } catch (RuntimeException e) {
                    throw new UpdateOrderException("");
                }
            }
        } else {
            if (StringUtils.isNotEmpty(express.get("number"))) {
                try {
                    Fulfillment fulfillment = fulfillmentService.get(new Long(express.get("id")));
                    if (null == fulfillment) {
                        throw new UpdateOrderException("");
                    }
                    fulfillment.setNumber(express.get("number"));
                    fulfillment.setCompanycode(express.get("companycode"));
                    fulfillment.setModifyDate(new Date());
                    fulfillmentService.update(fulfillment);
                    return fulfillment.getId();
                } catch (RuntimeException e) {
                    throw new UpdateOrderException("");
                }
            } else {
                throw new UpdateOrderException("");
            }
        }
    }


    /**
     * insert物流信息
     *
     * @param express
     * @param orderId
     */
    private Long insertFulfillment(Map<String, String> express, Long orderId) {
        LOGGER_ORDERDETAILBIZIMPL.info("refund -> 添加物流信息");
        if (StringUtils.isNotEmpty(express.get("number"))) {
            LOGGER_ORDERDETAILBIZIMPL.info("refund -> 添加物流信息 -> success");
            Fulfillment fulfillment = new Fulfillment();
            fulfillment.setOrderid(orderId);
            fulfillment.setType(0);
            fulfillment.setStatus(1);
            if (StringUtils.isNotEmpty(express.get("number"))) {
                fulfillment.setNumber(express.get("number"));
            } else {
                fulfillment.setNumber("");
            }
            if (StringUtils.isNotEmpty(express.get("companycode"))) {
                fulfillment.setCompanycode(express.get("companycode"));
            } else {
                fulfillment.setCompanycode("");
            }
            fulfillment.setSenddate(null);
            fulfillment.setArrivedate(null);
            fulfillment = fulfillmentService.save(fulfillment);
            return fulfillment.getId();
        } else {
            LOGGER_ORDERDETAILBIZIMPL.info("refund -> 添加物流信息 -> number is null,insert cancel.");
            return -1L;
        }
    }

    @Override
    @Transactional
    public Boolean updatePayVoucher(UploadToDBInfo uploadToDBInfo) {
        List<OrderPayVoucher> vouchers = orderPayVoucherService.getForOrderId(new Long(uploadToDBInfo.getMainId()), new Long(uploadToDBInfo.getSubId()));
        if (vouchers.size() > 0) {
            for (OrderPayVoucher voucher : vouchers) {
                voucher.setDisabledflag(true);
                orderPayVoucherService.update(voucher);
            }
        }
        String[] urls = uploadToDBInfo.getUrl();
        for (String url : urls) {
            OrderPayVoucher orderPayVoucher = new OrderPayVoucher();
            orderPayVoucher.setOrderid(new Long(uploadToDBInfo.getMainId()));
            orderPayVoucher.setPaymentid(new Long(uploadToDBInfo.getSubId()));
            orderPayVoucher.setUrl(url.replace(File.separator, "/"));
            orderPayVoucherService.save(orderPayVoucher);
            //如果发现图片是临时路径则重新上传生成正式的
            if (orderPayVoucher.getUrl().contains("/"
                    + com.vogue.supplymall.common.constant.ConstantBean.SYSTEM_NAME
                    + "/" + UploadService.TEMP_PATH)) {
                UploadInfo uploadInfo = new UploadInfo();
                uploadInfo.setDataid(orderPayVoucher.getId());
                uploadInfo.setSourcepath(orderPayVoucher.getUrl());
                if (orderPayVoucher.getUrl().contains(".")) {
                    uploadInfo.setExtension(orderPayVoucher.getUrl().substring(orderPayVoucher.getUrl().lastIndexOf(".")) + 1);
                }
                uploadInfo.setModuleName(
                        com.vogue.supplymall.upload.domain.bean.ConstantBean.PAY_VOUCHER_MODULE_NAME
                                + "/" + orderPayVoucher.getOrderid()
                                + "/" + orderPayVoucher.getPaymentid());
                uploadService.uploadResource(uploadInfo);
            }
        }
        return true;
    }

    @Override
    public List<OrderPayVoucher> getOrderDetailPayVoucher(UploadToDBInfo uploadToDBInfo) {
        List<OrderPayVoucher> vouchers = orderPayVoucherService.getForOrderId(new Long(uploadToDBInfo.getMainId()), new Long(uploadToDBInfo.getSubId()));
        if (vouchers.size() > 0) {
            for (OrderPayVoucher voucher : vouchers) {
                voucher.setCreateDate(null);
                voucher.setModifyDate(null);
                voucher.setDisabledflag(null);
            }
        }
        return vouchers;
    }
}
